package com.sharp.portal.controller;

import com.github.pagehelper.PageInfo;
import com.sharp.authorization.holder.TokenHolder;
import com.sharp.framework.utils.HttpUtil;
import com.sharp.kernel.config.response.Response;
import com.sharp.kernel.config.response.ResponseHandler;
import com.sharp.kernel.constant.CommonConst;
import com.sharp.kernel.utils.DbUtil;
import com.sharp.kernel.vo.common.CommonResVO;
import com.sharp.kernel.vo.common.DeleteCommonReqVO;
import com.sharp.kernel.vo.query.QueryReqVO;
import com.sharp.kernel.vo.query.QueryRespVO;
import com.sharp.portal.service.BasePortalUploadService;
import com.sharp.portal.service.PortalCommonService;
import com.sharp.portal.service.PortalManageService;
import com.sharp.portal.utils.PortalUtil;
import com.sharp.portal.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.multipart.MultipartFile;
import springfox.documentation.annotations.ApiIgnore;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * Title: BaseCommonController
 * Description: Copyright: Copyright (c) 2019 Company: BHFAE
 *
 * @author Sharp
 * @date 2021/2/15 21:58
 */
@Slf4j
public abstract class BaseCommonController extends PortalCommonController {

    @Resource
    private PortalManageService portalManageService;

    @ApiIgnore
    @RequestMapping(value = "/model", method = RequestMethod.GET)
    public ResponseEntity<Response<ModelDisplayVO>> getModelDisplay(HttpServletRequest request) {
        String uri = getCurrentUri(request);
        ModelDisplayVO vo = portalManageService.getModelDisplay(uri);
        return ResponseHandler.generateResponse(vo);
    }

    @ApiIgnore
    @RequestMapping(value = "/layout", method = RequestMethod.GET)
    public ResponseEntity<Response<LinkedHashMap<String, FieldDisplayVO>>> getFieldDisplay(HttpServletRequest request) {
        String uri = getCurrentUri(request);
        LinkedHashMap<String, FieldDisplayVO> map = portalManageService.getFieldDisplayMap(uri);
        return ResponseHandler.generateResponse(map);
    }

    @ApiIgnore
    @RequestMapping(value = "/id", method = RequestMethod.GET)
    public ResponseEntity<Response<QueryRespVO<Map<String, String>>>> getById(Object id) {
        QueryRespVO<Map<String, String>> res = getManageService().getById(id);
        return ResponseHandler.generateResponse(res);
    }

    /**
     * 获取manageService
     *
     * @return manageService
     */
    protected abstract PortalCommonService getManageService();

    @ApiIgnore
    @RequestMapping(value = "", method = RequestMethod.GET)
    public ResponseEntity<Response<QueryRespVO<Map<String, String>>>> getAll(QueryReqVO req) {
        PageInfo<?> pageInfo = DbUtil.buildPageInfo(req);
        QueryRespVO<Map<String, String>> res = getManageService().getAll(pageInfo);
        return ResponseHandler.generateResponse(res);
    }

    @ApiIgnore
    @RequestMapping(value = "/query", method = RequestMethod.POST)
    public ResponseEntity<Response<QueryRespVO<Map<String, String>>>> query(HttpServletRequest request,
                                                                            @RequestBody QueryConditionReq req) {
        PageInfo<?> pageInfo = DbUtil.buildPageInfo(req);
        if (CollectionUtils.isNotEmpty(req.getConditionList())) {
            req.getConditionList().addAll(fillCondition(request));
        } else {
            req.setConditionList(fillCondition(request));
        }
        QueryRespVO<Map<String, String>> res = getManageService().query(req, pageInfo);
        return ResponseHandler.generateResponse(res);
    }

    protected List<ConditionVO> fillCondition(HttpServletRequest request) {
        return PortalUtil.fillCondition(request);
    }

    @ApiIgnore
    @RequestMapping(value = "/export", method = RequestMethod.POST)
    public void export(HttpServletRequest request, HttpServletResponse response, @RequestBody QueryConditionReq req) {
        QueryRespVO<Map<String, String>> res = getManageService().query(req, null);
        HttpUtil.attachmentExcel(res.getInfo(), request, response);
    }

    @ApiIgnore
    @RequestMapping(value = "/tree", method = RequestMethod.GET)
    public ResponseEntity<Response<List<TreeDisplayVO>>> getTree(HttpServletRequest request) {
        String uri = getCurrentUri(request);
        QueryRespVO<Map<String, String>> res = getManageService().getAll(null);
        List<TreeDisplayVO> tree = portalManageService.getTreeDisplay(uri, res.getInfo());
        return ResponseHandler.generateResponse(tree);
    }

    @ApiIgnore
    @RequestMapping(value = "", method = RequestMethod.PUT)
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity<Response<CommonResVO>> add(@RequestBody Map<String, String> req) {
        int number = getManageService().add(req);
        String result = number == 0 ? CommonConst.FAILED : CommonConst.SUCCESS;
        return ResponseHandler.commonResponse(result, number);
    }

    @ApiIgnore
    @RequestMapping(value = "", method = RequestMethod.POST)
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity<Response<CommonResVO>> update(@RequestBody Map<String, String> req) {
        int number = getManageService().update(req);
        String result = number == 0 ? CommonConst.FAILED : CommonConst.SUCCESS;
        return ResponseHandler.generateResponse(new CommonResVO(result, number));
    }

    @ApiIgnore
    @RequestMapping(value = "", method = RequestMethod.DELETE)
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity<Response<CommonResVO>> delete(DeleteCommonReqVO req) {
        int number;
        if (StringUtils.equals(req.getAbsolute(), CommonConst.YES)) {
            number = getManageService().delete(req);
        } else {
            number = getManageService().disable(req);
        }
        String result = number == 0 ? CommonConst.FAILED : CommonConst.SUCCESS;
        return ResponseHandler.commonResponse(result, number);
    }

    @ApiIgnore
    @RequestMapping(value = "/refresh", method = RequestMethod.POST)
    public ResponseEntity<Response<CommonResVO>> refresh() {
        getManageService().refreshCache();
        return ResponseHandler.commonResponse();
    }

    @ApiIgnore
    @RequestMapping(value = "/template/export", method = RequestMethod.GET)
    public void getTemplate(HttpServletRequest request, HttpServletResponse response) {
        HttpUtil.attachmentExcel(getUploadVO(), request, response);
    }

    /**
     * 获取上传文件模板类Class
     *
     * @return 上传文件模板类Class
     */
    protected abstract Class<?> getUploadVO();

    @ApiIgnore
    @RequestMapping(value = "/upload/progress", method = RequestMethod.GET)
    public ResponseEntity<Response<CommonResVO>> uploadProgress() {
        String res = getUploadService().getUploadProgress();
        return ResponseHandler.commonResponse(res);
    }

    /**
     * 获取uploadService
     *
     * @return uploadService
     */
    protected abstract BasePortalUploadService getUploadService();

    protected String getToken() {
        return TokenHolder.get();
    }

    @ApiIgnore
    @RequestMapping(value = "/upload", method = RequestMethod.POST)
    public ResponseEntity<Response<CommonResVO>> uploadExcel(MultipartFile file) {
        try {
            File tempFile = File.createTempFile("tmp", null);
            file.transferTo(tempFile);
            getUploadService().uploadExcel(tempFile);
            tempFile.deleteOnExit();
        } catch (IOException e) {
            log.error("", e);
        }
        return ResponseHandler.commonResponse();
    }
}
